using System;
using System.Workflow.ComponentModel;
using System.IO.Packaging;
using System.Xml.Schema;
using System.Xml;
using System.IO;
using System.Collections.Generic;

namespace OWA.Activities
{
	public class ValidatePackageActivity
        : AbstractPackageActivity
	{
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            Package package = GetPackage();
            XmlSchemaSet schemas = SchemaLoader.GetAllSchemas();
            foreach (PackagePart part in package.GetParts())
            {
                if (IsXmlPart(part))
                {
                    ValidatePart(part, schemas);
                }
            }
            return ActivityExecutionStatus.Closed;
        }

        bool IsXmlPart(PackagePart part)
        {
            string contentType = part.ContentType;
            string[] contentTypeParts = contentType.Split('/', '.', '+');
            return String.Equals(
                contentTypeParts[contentTypeParts.Length - 1],
                "xml", StringComparison.InvariantCultureIgnoreCase);
        }

        void ValidatePart(PackagePart part, XmlSchemaSet schemas)
        {
            XmlDocument document = new XmlDocument();
            try
            {
                using (Stream stream = part.GetStream(FileMode.Open, FileAccess.Read))
                {
                    document.Load(stream);
                }
            }
            catch (XmlException e)
            {
                string partUri = part.Uri.ToString();
                string message = String.Format("The {0} part could not be loaded", partUri);
                throw new PackageValidationException(
                    message, e);
            }
            document.Schemas.Add(schemas);
            try
            {
                document.Validate(null);
            }
            catch(XmlSchemaValidationException e)
            {
                string partUri = part.Uri.ToString();
                string message = String.Format("The {0} part failed validation at line {1} with the error: {2}", partUri, e.LineNumber, e.Message);
                throw new PackageValidationException(
                    message, e);
            }
        }
	}
}
